#include "../include/factory.hpp"
#include "../include/sql.hpp"
int main(int argc, char *argv[])
{
    srand((unsigned int)time(nullptr));
    ARGS_CHECK(argc, 2);
    FILE *fp = fopen(argv[1], "r+");
    ERROR_CHECK(fp, NULL, "fopen");
    int socket_fd;
    tcpInit(&socket_fd, fp);
    fclose(fp);
    client_t client[SOCKET_NUM];
    for (int i = 0; i < SOCKET_NUM; i++)
    {
        client[i].state = 0;
    }
    int epfd = epoll_create(1);
    struct epoll_event evs[SOCKET_NUM];
    epoll_func(epfd, socket_fd, EPOLL_CTL_ADD, EPOLLIN);
    struct sockaddr_in clien;
    int clientfd;
    int client_sum = 0;
    int ret = 0;
    char temp[50];
    socklen_t len = 0;
    Train_t train;
    Zhuce login_msg;
    QUR_msg qq_msg;
    MYSQL *conn;
    sql_connect(&conn);
    Llog(conn, "Server Start", "---", "---", "---");
    while (true)
    {
        int ready_num = epoll_wait(epfd, evs, SOCKET_NUM, -1);
        int fd = 0;
        for (int i = 0; i < ready_num; i++)
        {
            fd = evs[i].data.fd;
            if (evs[i].events == EPOLLIN && fd == socket_fd)
            {
                len = sizeof(clien);
                clientfd = accept(socket_fd, (struct sockaddr *)&clien, &len);
                client[clientfd].state = 1;
                client_sum++;
                client[clientfd].code = 0;
                epoll_func(epfd, clientfd, EPOLL_CTL_ADD, EPOLLIN);
                sprintf(client[clientfd].name, "ip:%s port:%d",
                        inet_ntoa(clien.sin_addr), ntohs(clien.sin_port));
                Llog(conn, "Connect", "---", client[clientfd].name, "Request");
                continue;
            }
            if (client[fd].state > 0)
            {
                ret = one_recv(fd, &train);
                if (ret == -1)
                {
                    //.......
                    Llog(conn, "Client quit", client[fd].name, "---", "Sucess");
                    close(fd);
                    client[fd].state = 0;
                    client[fd].code = 0;
                    client_sum--;
                    epoll_func(epfd, fd, EPOLL_CTL_DEL, EPOLLIN);
                    continue;
                }
                switch (train.ctl_code)
                {
                case LOGIN_PRE:
                    Llog(conn, "Login request", train.buf, client[fd].name, "Sucess");
                    client[fd].state = 1;
                    strcpy(client[fd].name, train.buf);
                    ret = find_name(conn, client[fd].name, nullptr);
                    if (ret == 0)
                    {
                        train.len = 0;
                        train.ctl_code = LOGIN_NO;
                        send(fd, &train, 8, 0);
                    }
                    else
                    {
                        get_salt(train.buf);
                        train.len = strlen(train.buf) + 1;
                        train.ctl_code = LOGIN_POK;
                        send(fd, &train, train.len + 8, 0);
                    }
                    break;
                case LOGIN_Q:
                    memcpy(&login_msg, train.buf, train.len);
                    add_user(conn, login_msg.name, login_msg.token, login_msg.passward);
                    Olog(conn, client[fd].name, "Login ", "---", "Sucess");
                    break;
                case REGISTER_PRE:
                    Llog(conn, "Register request", train.buf, client[fd].name, "Sucess");
                    client[fd].state = 1;
                    strcpy(client[fd].name, train.buf);
                    ret = find_name(conn, client[fd].name, train.buf);
                    if (ret == -1)
                    {
                        train.len = 0;
                        train.ctl_code = REGISTER_NO;
                    }
                    else
                    {
                        train.len = strlen(train.buf) + 1;
                        train.ctl_code = REGISTER_POK;
                    }
                    send(fd, &train, train.len + 8, 0);
                    break;
                case REGISTER_Q:
                    memcpy(&login_msg, train.buf, train.len);
                    ret = math_user(conn, login_msg.name, login_msg.passward, login_msg.token);
                    if (ret == -1)
                    {
                        train.len = 0;
                        train.ctl_code = REGISTER_NO;
                        Olog(conn, client[fd].name, "Register ", "---", "False");
                    }
                    else
                    {
                        train.len = 0;
                        train.ctl_code = REGISTER_OK;
                        strcpy(client[fd].name, login_msg.name);
                        client[fd].state = 2;
                        Olog(conn, client[fd].name, "Register ", "---", "Success");
                    }
                    send(fd, &train, train.len + 8, 0);
                    break;
                case TOKEN_PLESE:
                    break;
                case LS_Q:
                    if (client[fd].state == 2)
                    {
                        Olog(conn, client[fd].name, "Ls", "---", "Success");
                        ls_func(conn, client[fd].name, client[fd].code, train.buf);
                        train.ctl_code = LS_OK;
                        train.len = strlen(train.buf) + 1;
                    }
                    else
                    {
                        train.ctl_code = REGISTER_NO;
                        train.len = 0;
                    }
                    send(fd, &train, train.len + 8, 0);
                    break;
                case OPERATE_Q:
                    if (client[fd].state == 2)
                    {
                        memcpy(&qq_msg, train.buf, train.len);
                        strcpy(temp, qq_msg.buf);
                        Olog(conn, client[fd].name, qq_msg.buf, qq_msg.buf1, "Request");
                        ret = operate_func(conn, &train, &qq_msg, client[fd].name, &client[fd].code);
                        if (ret == -1)
                        {
                            Olog(conn, client[fd].name, temp, "---", "False");
                            train.len = 0;
                            train.ctl_code = OPERATE_NO;
                        }
                        else
                        {
                            Olog(conn, client[fd].name, temp, "---", "Success");
                        }
                    }
                    else
                    {
                        train.ctl_code = REGISTER_NO;
                        train.len = 0;
                    }
                    send(fd, &train, train.len + 8, 0);
                    break;
                }
            }
        }
    }
    return 0;
}